/*!
 * \file te_core.h
 *
 * \brief TongEASY模块主文件
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.
 *
 * \version 1.0
 * \author songbb
 * \date 2016/09/24
 *
 */

#ifndef __TE_CORE_H_
#define __TE_CORE_H_

#include "frlist.h"
#include "frhash2.h"
#include "frstr.h"

#include "conntrack.h"
#include "module.h"
#include "frbyte_buffer.h"

/*! @brief 常用包类型 */
typedef enum __em_te_pkt_type {
    TE_PKT_TYPE_UNKNOWN = 0,
    TE_PKT_TYPE_SYNC_ASYNC_REQ,             //!< 5Z0200 – 用户同步/异步请求包
    TE_PKT_TYPE_SYNC_ASYNC_RESP,            //!< 5Z0210 – 用户同步/异步应答包
    TE_PKT_TYPE_SYNC_ASYNC_COMMIT_REQ,      //!< 5Z0202 – 用户同步/异步提交包
    TE_PKT_TYPE_SYNC_ASYNC_COMMIT_RESP,     //!< 5Z0212 - 用户同步/异步提交应答包
    TE_PKT_TYPE_SYNC_ASYNC_ABORT_REQ,       //!< 5Z0402 – 用户同步/异步回滚包
    TE_PKT_TYPE_SYNC_ASYNC_ABORT_RESP,      //!< 5Z0412 – 用户同步/异步回滚应答包
    TE_PKT_TYPE_CVS_REQ,                    //!< 5C0200 – 用户会话交易传输请求包
    TE_PKT_TYPE_CVS_RESP,                   //!< 5C0202 – 用户会话交易传输响应包
    TE_PKT_TYPE_CVS_CONN_REQ,               //!< 5C0800 - 用户会话交易建立连接请求包
    TE_PKT_TYPE_CVS_CONN_RESP,              //!< 5C0810 - 用户会话交易建立连接应答包
    TE_PKT_TYPE_CVS_DISCONN,                //!< 5C0402 - 用户会话交易拆除连接通知包
} TE_pkt_type;

/*! @brief TongEASY协议通用包头 */
typedef struct __st_te_header
{
    unsigned int ui_header_len;         //!< 消息头长度 - 到全局事务超时时间为止
    unsigned int ui_pkt_len;            //!< 消息体长度(包含消息头)
    TE_pkt_type pkt_type;               //!< 常用包类型
    int i_ptxflag;                      //!< PTxFlag
    int i_branchflag;                   //!< BranchFlag
    int i_tid;                          //!< 事务序号
    int i_subtid;                       //!< 事务分支序号
    char arr_original_node[13];         //!< 发起节点名
    char arr_send_node[13];             //!< 发送节点名
    char arr_recv_node[13];             //!< 接收节点名
    char arr_svcname[21];               //!< 服务名
    short s_ret_code;                   //!< 响应码
    int i_user_data_len;                //!< 用户数据长度
    int i_filename_len;                 //!< 文件名长度
    int i_key_data_len;                 //!< 关键数据长度
} TE_header;

/*! @brief 分片的状态 */
typedef enum __em_fragment_state {
    APM_TE_FRAGMENT_INIT,                     //!< 初始化
    APM_TE_FRAGMENT_NEED_NEXT_REQ_PACKET,     //!< 需要下一个请求包
    APM_TE_FRAGMENT_NEED_NEXT_RESP_PACKET     //!< 需要下一个响应包
} TE_fragment_state;

/*! @brief TongEASY数据包 */
typedef struct __st_L7_te_packet
{
    TE_header st_te_header;                 //!< 包头
    TE_fragment_state fragment_state;       //!< 当前的分片状态
    Frbyte_Packet *p_st_packet;             //!< 组包完成的数据
    unsigned int ui_len_to_read;            //!< 还需要从下一个payload中读取多少个字节
    struct timeval st_timestamp_first;      //!< 第一个请求的分片包的时间
    struct timeval st_timestamp_last;       //!< 最后一个请求的分片包的时间
    int i_is_req;                           //!< 是否是请求包
} L7_te_packet;

/*! @brief TongEASY交易信息 */
typedef struct __st_L7_te_stmt
{
    Frlist_header *p_report_comm;           //!< 用于临时存储report的公共部分数据
    Frlist_header *p_report_req;            //!< 用于临时存储report的请求部分数据
    struct timeval st_req_end_timestamp;    //!< 请求的结束时间戳
    struct timeval st_resp_start_timestamp; //!< 响应的开始时间戳
} L7_te_stmt;

/*! @brief TongEASY私有结构体 */
typedef struct __st_L7session_te_private
{
    Frhash_header *p_hash_stmt;              //!< 按 事务序号*10000+事务分支序号 建立hash
    L7_te_packet *p_st_te_packet;            //!< 当前处理中的TongEASY数据包
    L7_session *p_st_session;                //!< 指向父级的L7_session结构体
    struct timeval st_timestamp;             //!< 用于检查stmt超时
} L7session_te_private;

/**
 * 用于存储在detect过程中的中间数据
 */
typedef struct __st_te_detect_session
{
    char c_detect_succ_count;               //!< detect成功的次数
} TE_detect_session;

/*!
 * 判断当前数据链路是否是TongEASY协议的
 *
 * \param p_st_conn        (ct信息)
 * \param p_st_packet      (协议分析入力数据)
 *
 * \return 参照module.h中APM_L7_IS_的定义
 *
 */
int te_detect(Conntrack *p_st_conn
                , Apm_packet *p_st_packet);

/*!
 * TongEASY协议解析入口
 *
 * \param p_st_conn             (ct信息)
 * \param p_st_packet           (协议分析入力数据)
 * \param p_st_hash_report      (保存Frreport_data)
 *
 * \return 参照module.h中APM_L7_ANALYZE_的定义
 *
 */
int te_analyze(Conntrack *p_st_conn
                , Apm_packet *p_st_packet
                , Frhash_header *p_st_hash_report);

/*!
 * 释放TongEASY private数据
 *
 * \param p_st_session_private_in        (TongEASY的私有信息)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int te_session_destory(void *p_st_session_private_in);

#endif
